package com.lap.dev.starter.shared;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Predicate;
import lombok.experimental.UtilityClass;

@UtilityClass
public class NetworkUtil {

  /**
   * 获取本机所有真实可用的IPv4地址 自动排除以下类型地址： - IPv6地址 - 回环地址 (127.0.0.1) - 链路本地地址 (169.254.x.x) - 未启用的网络接口 -
   * 虚拟网络接口 - 回环接口
   */
  public static Set<String> getAvailableIPv4Addresses() {
    return getAvailableIPv4Addresses(true, true, true, true);
  }

  /**
   * 高级方法：自定义获取真实可用的IPv4地址
   *
   * @param excludeLoopBack 是否排除回环地址 (127.0.0.1等)
   * @param excludeLinkLocal 是否排除链路本地地址 (169.254.x.x)
   * @param excludeVirtualInterfaces 是否排除虚拟网卡
   * @param onlyUpInterfaces 是否只考虑已启用的网络接口
   * @return 可用的IPv4地址集合
   */
  public static Set<String> getAvailableIPv4Addresses(
      boolean excludeLoopBack,
      boolean excludeLinkLocal,
      boolean excludeVirtualInterfaces,
      boolean onlyUpInterfaces) {

    Set<String> result = new HashSet<>();
    Predicate<InetAddress> addressFilter = addr -> addr instanceof Inet4Address; // 保证只返回IPv4地址

    if (excludeLoopBack) {
      addressFilter = addressFilter.and(addr -> !addr.isLoopbackAddress());
    }
    if (excludeLinkLocal) {
      addressFilter = addressFilter.and(addr -> !addr.isLinkLocalAddress());
    }

    try {
      // 获取所有网络接口
      for (NetworkInterface anInterface :
          Collections.list(NetworkInterface.getNetworkInterfaces())) {
        // 应用接口过滤
        try {
          if (onlyUpInterfaces && !anInterface.isUp()) continue;
          if (excludeVirtualInterfaces && anInterface.isVirtual()) continue;
          if (excludeLoopBack && anInterface.isLoopback()) continue;
        } catch (SocketException e) {
          // 出现异常时跳过该接口
          continue;
        }

        // 获取该接口的所有地址
        for (InetAddress addr : Collections.list(anInterface.getInetAddresses())) {
          // 应用地址过滤
          if (addressFilter.test(addr)) {
            result.add(addr.getHostAddress());
          }
        }
      }
    } catch (SocketException e) {
      throw new RuntimeException("获取网络接口时出错", e);
    }

    return result;
  }

  /** 获取首选可用IPv4地址（通常是最主要的非内网地址） 如果没有找到合适的地址，返回null */
  public static String getPrimaryIPv4Address() {
    Set<String> addresses = getAvailableIPv4Addresses();
    for (String addr : addresses) {
      // 优先选择非内网地址
      if (!isPrivateIPv4(addr)) {
        return addr;
      }
    }
    // 其次选择内网地址
    return addresses.isEmpty() ? null : addresses.iterator().next();
  }

  /** 判断是否为私有IPv4地址 */
  private static boolean isPrivateIPv4(String ip) {
    if (ip == null) return false;

    // 私有地址范围：
    // 10.0.0.0 - 10.255.255.255
    // 172.16.0.0 - 172.31.255.255
    // 192.168.0.0 - 192.168.255.255
    return ip.startsWith("10.")
        || ip.startsWith("192.168.")
        || (ip.startsWith("172.") && isIn172Range(ip));
  }

  private static boolean isIn172Range(String ip) {
    String[] parts = ip.split("\\.");
    if (parts.length < 2) return false;
    try {
      int secondOctet = Integer.parseInt(parts[1]);
      return secondOctet >= 16 && secondOctet <= 31;
    } catch (NumberFormatException e) {
      return false;
    }
  }
}
